package com.zhentao.websocket;


import com.alibaba.fastjson2.JSON;
import com.zhentao.config.GetHttpSessionConfig;
import com.zhentao.pojo.User;
import com.zhentao.service.ChatMessageService;
import com.zhentao.service.ChatGroupMessageService;
import com.zhentao.service.GroupMemberService;
import com.zhentao.utils.MessageUtils;
import com.zhentao.utils.SpringContextUtils;
import com.zhentao.websocket.pojo.Message;
import com.zhentao.websocket.pojo.ChatMessage;
import com.zhentao.websocket.pojo.ChatGroupMessage;
import com.zhentao.websocket.pojo.ResultMessage;
import jakarta.servlet.http.HttpSession;
import jakarta.websocket.*;
import jakarta.websocket.server.PathParam;
import jakarta.websocket.server.ServerEndpoint;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
import org.springframework.web.context.support.WebApplicationContextUtils;

import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

@ServerEndpoint(value = "/chat", configurator = GetHttpSessionConfig.class)
@Component
public class ChatEndpoint {

    // 保存在线的用户，key为用户ID，value为 Session 对象
    private static final Map<Integer, Session> onlineUsers = new ConcurrentHashMap<>();

    // 保存Session与用户ID的映射
    private static final Map<Session, Integer> sessionUsers = new ConcurrentHashMap<>();

    // 保存用户ID与用户名的映射（用于显示和日志）
    private static final Map<Integer, String> userNames = new ConcurrentHashMap<>();

    private Integer currentUserId;
    private String currentUserName;

    // 服务实例（通过ApplicationContext获取）
    private static ChatMessageService chatMessageService;
    private static ChatGroupMessageService chatGroupMessageService;
    private static GroupMemberService groupMemberService;

    /**
     * 静态初始化服务实例
     * 在Spring容器启动后调用
     */
    public static void initializeStaticServices() {
        try {
            if (SpringContextUtils.isInitialized()) {
                chatMessageService = SpringContextUtils.getBean(ChatMessageService.class);
                chatGroupMessageService = SpringContextUtils.getBean(ChatGroupMessageService.class);
                groupMemberService = SpringContextUtils.getBean(GroupMemberService.class);
                System.out.println("ChatEndpoint静态服务初始化成功");
            } else {
                System.err.println("SpringContextUtils未初始化，无法初始化ChatEndpoint服务");
            }
        } catch (Exception e) {
            System.err.println("ChatEndpoint静态服务初始化失败: " + e.getMessage());
            e.printStackTrace();
        }
    }

    /**
     * 建立websocket连接后，被调用
     *
     * @param session Session
     */
    @OnOpen
    public void onOpen(Session session, EndpointConfig config) {
        System.out.println("WebSocket连接建立: " + session.getId());

        // 确保服务实例已初始化
        ensureServicesInitialized(config);

        try {
            // 从配置中获取查询参数
            String queryString = (String) config.getUserProperties().get("queryString");
            String username = null;
            Integer userId = null;

            if (queryString != null) {
                String[] params = queryString.split("&");
                for (String param : params) {
                    if (param.startsWith("username=")) {
                        username = java.net.URLDecoder.decode(param.substring(9), "UTF-8");
                    } else if (param.startsWith("userId=")) {
                        try {
                            userId = Integer.parseInt(param.substring(7));
                        } catch (NumberFormatException e) {
                            System.err.println("无效的用户ID: " + param.substring(7));
                        }
                    }
                }
            }

            if (userId != null && username != null && !username.trim().isEmpty()) {
                this.currentUserId = userId;
                this.currentUserName = username;

                // 使用用户ID作为key存储Session
                onlineUsers.put(userId, session);
                sessionUsers.put(session, userId);
                userNames.put(userId, username);

                System.out.println("用户 " + username + " (ID: " + userId + ") 已连接");

                // 通知所有用户，当前用户上线了
                String message = MessageUtils.getMessage(true, null, getFriends());
                broadcastAllUsers(message);
            } else {
                System.out.println("用户ID或用户名为空，关闭连接。userId=" + userId + ", username=" + username);
                session.close();
            }
        } catch (Exception e) {
            System.err.println("WebSocket连接处理失败: " + e.getMessage());
            e.printStackTrace();
            try {
                session.close();
            } catch (IOException ioException) {
                ioException.printStackTrace();
            }
        }
    }


    private Set<String> getFriends() {
        // 返回在线用户的用户名集合（用于兼容现有的消息格式）
        return userNames.values().stream().collect(Collectors.toSet());
    }

    private void broadcastAllUsers(String message) {
        try {
            Set<Map.Entry<Integer, Session>> entries = onlineUsers.entrySet();

            for (Map.Entry<Integer, Session> entry : entries) {
                // 获取到所有用户对应的 session 对象
                Session session = entry.getValue();

                // 使用 getBasicRemote() 方法发送同步消息
                session.getBasicRemote().sendText(message);
            }
        } catch (Exception exception) {
            exception.printStackTrace();
        }
    }

    /**
     * 浏览器发送消息到服务端时该方法会被调用，也就是私聊
     * 张三  -->  李四
     *
     * @param message String
     */
    @OnMessage
    public void onMessage(String message, Session session) {
        System.out.println("收到消息,原始string 类型: " + message);

        try {
            // 确保服务已初始化
            if (chatMessageService == null || chatGroupMessageService == null || groupMemberService == null) {
                System.err.println("服务未初始化，尝试重新初始化...");
                initializeStaticServices();
                if (chatMessageService == null || chatGroupMessageService == null || groupMemberService == null) {
                    System.err.println("服务初始化失败，无法处理消息");
                    return;
                }
            }

            // 处理心跳消息
            if ("ping".equals(message)) {
                session.getBasicRemote().sendText("pong");
                return;
            }

            // 将消息推送给指定的用户
            Message msg = JSON.parseObject(message, Message.class);
            System.out.println("收到的消息msg: "+msg.toString());
            String fromUser = String.valueOf(sessionUsers.get(session));

            if (fromUser == null) {
                System.err.println("发送者用户名未找到");
                return;
            }

            // 获取消息内容和类型
            String tempMessage = msg.getMessage();
            String messageType = msg.getMessageType() != null ? msg.getMessageType() : "text";
            String chatType = msg.getChatType() != null ? msg.getChatType() : "private";

            // 判断是私聊还是群聊
            if (msg.isGroupMessage()) {
                // 处理群聊消息
                Long groupId = msg.getGroupId();
                System.out.println("收到群聊消息: 群组ID=" + groupId + ", 发送者=" + fromUser + ", 类型=" + messageType);

                // 保存群聊消息到 mongodb数据库
                try {
                    if (chatGroupMessageService != null) {
                        ChatGroupMessage groupMessage = new ChatGroupMessage(groupId, fromUser, tempMessage);
                        groupMessage.setMessageType(messageType);
                        groupMessage.setFromId(msg.getFromId()); // 设置发送者ID

                        // 如果是图片消息，设置额外的图片信息
                        if ("image".equals(messageType)) {
                            groupMessage.setImageUrl(tempMessage); // 图片URL
                            groupMessage.setFileSize(msg.getFileSize()); // 文件大小
                            groupMessage.setOriginalFilename(msg.getOriginalFilename()); // 原始文件名
                        }
                        // 如果是视频消息，设置额外的视频信息
                        else if ("video".equals(messageType)) {
                            groupMessage.setVideoUrl(tempMessage); // 视频URL
                            groupMessage.setFileSize(msg.getFileSize()); // 文件大小
                            groupMessage.setOriginalFilename(msg.getOriginalFilename()); // 原始文件名
                            groupMessage.setVideoDuration(msg.getVideoDuration()); // 视频时长
                            groupMessage.setVideoWidth(msg.getVideoWidth()); // 视频宽度
                            groupMessage.setVideoHeight(msg.getVideoHeight()); // 视频高度
                            groupMessage.setVideoCoverUrl(msg.getVideoCoverUrl()); // 视频封面
                        }

                        chatGroupMessageService.saveMessage(groupMessage);
                        System.out.println("群聊消息保存成功: 群组ID=" + groupId + ", 发送者=" + fromUser + ", 类型=" + messageType);
                    } else {
                        System.err.println("ChatGroupMessageService未初始化，无法保存群聊消息");
                    }
                } catch (Exception e) {
                    System.err.println("保存群聊消息失败: " + e.getMessage());
                    e.printStackTrace();
                }

                // 广播给群组内的所有在线用户
                try {
                    if (groupMemberService != null) {
                        // 获取群成员用户ID列表
                        List<Long> groupMemberUserIds = groupMemberService.getGroupMemberUserIds(groupId);

                        if (!groupMemberUserIds.isEmpty()) {
                            // 构建群聊消息响应
                            ResultMessage resultMessage = new ResultMessage();
                            resultMessage.setFromId(msg.getFromId()); // 设置发送者ID
                            resultMessage.setSystem(false);
                            resultMessage.setFromName(fromUser);
                            resultMessage.setMessage(tempMessage);
                            resultMessage.setMessageType(messageType);
                            resultMessage.setChatType("group");
                            resultMessage.setGroupId(groupId);

                            // 如果是图片消息，设置图片相关字段
                            if ("image".equals(messageType)) {
                                resultMessage.setImageUrl(tempMessage); // 图片URL
                                resultMessage.setFileSize(msg.getFileSize()); // 文件大小
                                resultMessage.setOriginalFilename(msg.getOriginalFilename()); // 原始文件名
                            }
                            // 如果是视频消息，设置视频相关字段
                            else if ("video".equals(messageType)) {
                                resultMessage.setVideoUrl(tempMessage); // 视频URL
                                resultMessage.setFileSize(msg.getFileSize()); // 文件大小
                                resultMessage.setOriginalFilename(msg.getOriginalFilename()); // 原始文件名
                                resultMessage.setVideoDuration(msg.getVideoDuration()); // 视频时长
                                resultMessage.setVideoWidth(msg.getVideoWidth()); // 视频宽度
                                resultMessage.setVideoHeight(msg.getVideoHeight()); // 视频高度
                                resultMessage.setVideoCoverUrl(msg.getVideoCoverUrl()); // 视频封面
                            }

                            String messageToSend = JSON.toJSONString(resultMessage);

                            // 向所有在线的群成员广播消息（基于用户ID）
                            int sentCount = 0;
                            Integer fromUserId = msg.getFromId();

                            for (Long memberUserId : groupMemberUserIds) {
                                // 不向发送者自己发送消息
                                if (!memberUserId.equals(fromUserId.longValue())) {
                                    Session memberSession = onlineUsers.get(memberUserId.intValue());
                                    if (memberSession != null && memberSession.isOpen()) {
                                        try {
                                            memberSession.getBasicRemote().sendText(messageToSend);
                                            sentCount++;
                                        } catch (IOException e) {
                                            System.err.println("向群成员 ID:" + memberUserId + " 发送消息失败: " + e.getMessage());
                                        }
                                    }
                                }
                            }

                            System.out.println("群聊消息广播完成: 群组ID=" + groupId +
                                             ", 群成员总数=" + groupMemberUserIds.size() +
                                             ", 在线成员数=" + sentCount +
                                             ", 发送者=" + fromUser + " (ID:" + fromUserId + ")");
                        } else {
                            System.out.println("群组 " + groupId + " 没有成员，无法广播消息");
                        }
                    } else {
                        System.err.println("GroupMemberService未初始化，无法广播群聊消息");
                    }
                } catch (Exception e) {
                    System.err.println("群聊消息广播失败: " + e.getMessage());
                    e.printStackTrace();
                }

            } else if (msg.isPrivateMessage()) {
                // 处理私聊消息
                String toName = msg.getToName();

                // 保存私聊消息到数据库
                try {
                    if (chatMessageService != null) {
                        ChatMessage chatMessage = new ChatMessage();
                        //fromUser, toName, tempMessage, messageType)
                        chatMessage.setMessage(tempMessage);
                        chatMessage.setFromName(fromUser);
                        chatMessage.setToName(toName);
                        chatMessage.setMessageType(messageType);
                        chatMessage.setToId(msg.getToId());
                        chatMessage.setFromId(msg.getFromId());
                        chatMessage.setToAvatar(msg.getToAvatar());
                        System.out.println("保存私聊消息: " + chatMessage);
                        // 如果是图片消息，设置额外的图片信息
                        if ("image".equals(messageType)) {
                            chatMessage.setImageUrl(tempMessage); // 图片URL
                            chatMessage.setFileSize(msg.getFileSize()); // 文件大小
                            chatMessage.setOriginalFilename(msg.getOriginalFilename()); // 原始文件名
                        }
                        // 如果是视频消息，设置额外的视频信息
                        else if ("video".equals(messageType)) {
                            chatMessage.setVideoUrl(tempMessage); // 视频URL
                            chatMessage.setFileSize(msg.getFileSize()); // 文件大小
                            chatMessage.setOriginalFilename(msg.getOriginalFilename()); // 原始文件名
                            chatMessage.setVideoDuration(msg.getVideoDuration()); // 视频时长
                            chatMessage.setVideoWidth(msg.getVideoWidth()); // 视频宽度
                            chatMessage.setVideoHeight(msg.getVideoHeight()); // 视频高度
                            chatMessage.setVideoCoverUrl(msg.getVideoCoverUrl()); // 视频封面
                        }

                        chatMessageService.saveMessage(chatMessage);
                        System.out.println("私聊消息保存成功: " + fromUser + " -> " + toName + ", 类型=" + messageType);
                    } else {
                        System.err.println("ChatMessageService未初始化，无法保存私聊消息");
                    }
                } catch (Exception e) {
                    System.err.println("保存私聊消息失败: " + e.getMessage());
                    e.printStackTrace();
                }

                // 构建包含消息类型的响应消息
                ResultMessage resultMessage = new ResultMessage();
                resultMessage.setFromId(msg.getFromId()); // 发送者ID
                resultMessage.setToId(msg.getToId()); // 接收者ID
                resultMessage.setSystem(false);
                resultMessage.setFromName(fromUser);
                resultMessage.setMessage(tempMessage);
                resultMessage.setMessageType(messageType);
                resultMessage.setChatType("private");

                // 如果是图片消息，设置图片相关字段
                if ("image".equals(messageType)) {
                    resultMessage.setImageUrl(tempMessage); // 图片URL
                    resultMessage.setFileSize(msg.getFileSize()); // 文件大小
                    resultMessage.setOriginalFilename(msg.getOriginalFilename()); // 原始文件名
                }
                // 如果是视频消息，设置视频相关字段
                else if ("video".equals(messageType)) {
                    resultMessage.setVideoUrl(tempMessage); // 视频URL
                    resultMessage.setFileSize(msg.getFileSize()); // 文件大小
                    resultMessage.setOriginalFilename(msg.getOriginalFilename()); // 原始文件名
                    resultMessage.setVideoDuration(msg.getVideoDuration()); // 视频时长
                    resultMessage.setVideoWidth(msg.getVideoWidth()); // 视频宽度
                    resultMessage.setVideoHeight(msg.getVideoHeight()); // 视频高度
                    resultMessage.setVideoCoverUrl(msg.getVideoCoverUrl()); // 视频封面
                }

                // 设置头像信息
                resultMessage.setToAvatar(msg.getToAvatar());

                // 获取并设置发送方头像
                try {
                    String fromAvatar = getUserAvatar(msg.getFromId());
                    resultMessage.setFromAvatar(fromAvatar);
                } catch (Exception e) {
                    System.err.println("获取发送方头像失败: " + e.getMessage());
                }

                String messageToSend = JSON.toJSONString(resultMessage);

                // 使用用户ID获取Session对象
                Integer toUserId = msg.getToId();
                Integer fromUserId = msg.getFromId();

                // 获取消息接收方用户对象的 session 对象
                Session targetSession = onlineUsers.get(toUserId);
                if (targetSession != null && targetSession.isOpen()) {
                    targetSession.getBasicRemote().sendText(messageToSend);
                    System.out.println("私聊消息已发送给接收方: " + fromUser + " (ID:" + fromUserId + ") -> " + toName + " (ID:" + toUserId + ") (类型: " + messageType + ")");
                } else {
                    System.out.println("目标用户 " + toName + " (ID:" + toUserId + ") 不在线或连接已断开");
                }

                // 同时向发送方发送消息（让发送方也能实时看到自己发送的消息）
                Session senderSession = onlineUsers.get(fromUserId);
                if (senderSession != null && senderSession.isOpen() && !senderSession.equals(targetSession)) {
                    senderSession.getBasicRemote().sendText(messageToSend);
                    System.out.println("私聊消息已发送给发送方: " + fromUser + " (ID:" + fromUserId + ") (类型: " + messageType + ")");
                }
            } else {
                System.err.println("无效的消息类型或缺少必要参数");
            }
        } catch (Exception exception) {
            System.err.println("处理消息失败: " + exception.getMessage());
            exception.printStackTrace();
        }
    }

    /**
     * 断开 websocket 连接时被调用
     *
     * @param session Session
     */
    @OnClose
    public void onClose(Session session) {
        System.out.println("WebSocket连接断开: " + session.getId());

        try {
            // 从映射中获取用户ID
            Integer userId = sessionUsers.remove(session);

            if (userId != null) {
                // 从在线用户中移除
                onlineUsers.remove(userId);
                String username = userNames.remove(userId);
                System.out.println("用户 " + username + " (ID: " + userId + ") 已断开连接");

                // 通知其他用户，当前用户已下线
                String message = MessageUtils.getMessage(true, null, getFriends());
                broadcastAllUsers(message);
            }
        } catch (Exception e) {
            System.err.println("处理连接断开失败: " + e.getMessage());
            e.printStackTrace();
        }
    }

    /**
     * WebSocket发生错误时调用
     */
    @OnError
    public void onError(Session session, Throwable error) {
        System.err.println("WebSocket错误: " + error.getMessage());
        error.printStackTrace();

        // 清理连接
        String user = String.valueOf(sessionUsers.remove(session));
        if (user != null) {
            onlineUsers.remove(user);
        }
    }

    /**
     * 确保服务实例已初始化
     */
    private void ensureServicesInitialized(EndpointConfig config) {
        if (chatMessageService != null && chatGroupMessageService != null) {
            return; // 已经初始化，直接返回
        }

        initializeServices(config);
    }

    /**
     * 初始化服务实例
     */
    private void initializeServices(EndpointConfig config) {
        if (chatMessageService == null || chatGroupMessageService == null) {
            try {
                // 优先使用SpringContextUtils获取Bean
                if (SpringContextUtils.isInitialized()) {
                    chatMessageService = SpringContextUtils.getBean(ChatMessageService.class);
                    chatGroupMessageService = SpringContextUtils.getBean(ChatGroupMessageService.class);
                    System.out.println("WebSocket服务初始化成功（通过SpringContextUtils）");
                    return;
                }

                // 备用方案：从EndpointConfig中获取ServletContext
                Object servletContext = config.getUserProperties().get("servletContext");
                if (servletContext instanceof jakarta.servlet.ServletContext) {
                    ApplicationContext applicationContext = WebApplicationContextUtils
                            .getWebApplicationContext((jakarta.servlet.ServletContext) servletContext);

                    if (applicationContext != null) {
                        chatMessageService = applicationContext.getBean(ChatMessageService.class);
                        chatGroupMessageService = applicationContext.getBean(ChatGroupMessageService.class);
                        System.out.println("WebSocket服务初始化成功（通过ServletContext）");
                    } else {
                        System.err.println("无法从ServletContext获取ApplicationContext");
                    }
                } else {
                    System.err.println("无法从EndpointConfig获取ServletContext");
                }
            } catch (Exception e) {
                System.err.println("WebSocket服务初始化失败: " + e.getMessage());
                e.printStackTrace();
            }
        }
    }

    /**
     * 根据用户ID获取用户头像
     */
    private String getUserAvatar(Integer userId) {
        try {
            if (userId == null) {
                return null;
            }

            // 通过SpringContextUtils获取UserService
            if (SpringContextUtils.isInitialized()) {
                com.zhentao.service.UserService userService = SpringContextUtils.getBean(com.zhentao.service.UserService.class);
                if (userService != null) {
                    User user = userService.getOne(
                        new com.baomidou.mybatisplus.core.conditions.query.QueryWrapper<com.zhentao.pojo.User>()
                            .eq("id", Long.valueOf(userId))
                            .eq("status", 1)
                    );

                    if (user != null && user.getAvatar() != null &&
                        !user.getAvatar().trim().isEmpty() &&
                        !"identity_verified".equals(user.getAvatar())) {
                        return user.getAvatar();
                    }
                }
            }

            return null;
        } catch (Exception e) {
            System.err.println("查询用户 " + userId + " 头像失败: " + e.getMessage());
            return null;
        }
    }

}
